package maple.thelittleredbook.user.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import maple.thelittleredbook.common.service.EmailService;
import maple.thelittleredbook.user.entity.User;
import maple.thelittleredbook.user.entity.VerificationCode;
import maple.thelittleredbook.user.mapper.UserMapper;
import maple.thelittleredbook.user.mapper.VerificationCodeMapper;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Random;

@Slf4j
@Service
public class VerificationService {

    private final VerificationCodeMapper verificationCodeMapper;
    private final UserMapper userMapper;
    private final EmailService emailService;

    // 验证码发送频率限制（60秒）
    private static final int SEND_INTERVAL_SECONDS = 60;
    // 每小时最大发送次数
    private static final int MAX_SEND_PER_HOUR = 10;

    @Autowired
    public VerificationService(VerificationCodeMapper verificationCodeMapper,
                               UserMapper userMapper,
                               EmailService emailService) {
        this.verificationCodeMapper = verificationCodeMapper;
        this.userMapper = userMapper;
        this.emailService = emailService;
    }

    /**
     * 生成6位数字验证码
     *
     * @return 6位数字验证码
     */
    private String generateVerificationCode() {
        Random random = new Random();
        int code = 100000 + random.nextInt(900000); // 生成100000-999999之间的随机数
        return String.valueOf(code);
    }

    /**
     * 创建并发送验证码（带邮箱状态验证和防刷验证）
     *
     * @param email 邮箱地址
     * @param purpose 用途（email_verification/password_reset）
     * @return 是否发送成功
     */
    public boolean createAndSendVerificationCode(String email, String purpose) {
        // 1. 验证邮箱状态
        User existingUser = userMapper.selectByEmail(email);

        if ("email_verification".equals(purpose) && existingUser != null) {
            throw new IllegalArgumentException("该邮箱已注册");
        }

        if ("password_reset".equals(purpose) && existingUser == null) {
            throw new IllegalArgumentException("该邮箱未注册");
        }

        // 2. 检查发送频率限制
        LocalDateTime oneMinuteAgo = LocalDateTime.now().minusSeconds(SEND_INTERVAL_SECONDS);
        VerificationCode recentCode = verificationCodeMapper.selectLatestCodeByEmailAndPurpose(email, purpose);

        if (recentCode != null && recentCode.getCreatedAt().isAfter(oneMinuteAgo)) {
            log.warn("邮箱 {} 请求验证码过于频繁", email);
            throw new IllegalArgumentException("请求过于频繁，请稍后再试");
        }

        // 3. 检查每小时发送次数限制
        LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1);
        int recentCount = verificationCodeMapper.countRecentCodesByEmailAndPurpose(email, purpose, oneHourAgo);

        if (recentCount >= MAX_SEND_PER_HOUR) {
            log.warn("邮箱 {} 一小时内验证码发送次数超限", email);
            throw new IllegalArgumentException("一小时内发送次数过多，请稍后再试");
        }

        // 4. 生成验证码
        String code = generateVerificationCode();

        // 5. 设置过期时间
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime expiresAt;
        if ("email_verification".equals(purpose)) {
            expiresAt = now.plusMinutes(10); // 注册验证码10分钟
        } else if ("password_reset".equals(purpose)) {
            expiresAt = now.plusMinutes(15); // 密码重置验证码15分钟
        } else {
            throw new IllegalArgumentException("不支持的验证码用途: " + purpose);
        }

        // 6. 创建验证码实体
        VerificationCode verificationCode = new VerificationCode();
        verificationCode.setEmail(email);
        verificationCode.setToken(code);
        verificationCode.setPurpose(purpose);
        verificationCode.setCreatedAt(now);
        verificationCode.setExpiresAt(expiresAt);
        verificationCode.setIsUsed(false);

        try {
            // 7. 保存到数据库
            verificationCodeMapper.insert(verificationCode);
            log.info("为邮箱 {} 创建了用于 {} 的验证码", email, purpose);

            // 8. 发送验证码邮件
            boolean sent = emailService.sendVerificationCodeEmail(email, code, purpose);
            if (!sent) {
                log.error("验证码邮件发送失败: {}", email);
                return false;
            }

            return true;
        } catch (Exception e) {
            log.error("创建验证码失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 验证验证码是否有效
     *
     * @param email 邮箱
     * @param token 验证码令牌
     * @param purpose 用途
     * @return 验证结果
     */
    public boolean verifyCode(String email, String token, String purpose) {
        LocalDateTime now = LocalDateTime.now();

        // 查询该邮箱在指定用途下的有效验证码
        List<VerificationCode> validCodes = verificationCodeMapper.selectValidCodesByEmailAndPurpose(
                email, purpose, now
        );

        // 验证最新的验证码
        if (!validCodes.isEmpty()) {
            VerificationCode latestCode = validCodes.get(0); // 最新的验证码

            if (latestCode.getToken().equals(token)) {
                // 验证成功，标记为已使用
                verificationCodeMapper.markAsUsed(latestCode.getId(), now);
                log.info("验证码验证成功: 邮箱={}, 用途={}", email, purpose);
                return true;
            }
        }

        log.warn("验证码验证失败: 邮箱={}, 用途={}, 验证码={}", email, purpose, token);
        return false;
    }

    /**
     * 使一个邮箱的所有指定用途验证码失效
     *
     * @param email 邮箱
     * @param purpose 用途
     */
    public void invalidateAllCodes(String email, String purpose) {
        int count = verificationCodeMapper.invalidateAllCodes(email, purpose);
        log.info("使邮箱 {} 的 {} 个 {} 验证码失效", email, count, purpose);
    }
}